///
//  TurnFrames v 1.0
//  Russell Lowke, January 31st 2011
//
//  Copyright (c) 2011 Lowke Media
//  see http://www.lowkemedia.com for more information
//
//  Permission is hereby granted, free of charge, to any person obtaining a 
//  copy of this software and associated documentation files (the "Software"), 
//  to deal in the Software without restriction, including without limitation 
//  the rights to use, copy, modify, merge, publish, distribute, sublicense, 
//  and/or sell copies of the Software, and to permit persons to whom the 
//  Software is furnished to do so, subject to the following conditions:
// 
//  The above copyright notice and this permission notice shall be included in 
//  all copies or substantial portions of the Software.
// 
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
//  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 
//  IN THE SOFTWARE. 
//
//

function TurnFrames(angularVelocity, 			// (number) angulat velocity through which to turn through frames
					startAngle, 				// (number) starting angle
					targetAngle, 				// (number) angle being animated to
					type) 						// (string) type of effect, e.g. BaseFx.PERSIST
{
    this.clipSize;                       		// (uint) total number of images in clip for 360 degree rotation
    this.frame = 0;                            	// (number) float value of frame index
    this.angle = startAngle || 0;             	// (number) current angle in degrees, default 0
    this.targetAngle = targetAngle || 0;      	// (number) target angle in degrees
    this.angularVelocity = angularVelocity;   	// (number) angular velocity in degress per millisecond
    this.imageClip = 0;                      	// (ImageClip) this effect must target an image clip
    
    if (type) {                      // override type, should be PERSIST, WRAP, REVERSE, END, or REMOVE
        this.type = type;
    }
    
    this.activate = function() 
    {
        // target must be an ImageClip
        if (this.target instanceof ImageClip) {
            this.imageClip = this.target;
            
            // ImageClip's mspf must be 0
            this.imageClip.fps = 0;
            this.imageClip.mspf = 0;
            
        } else {
            throw new Error("TurnFrames must target an ImageClip.");
        }
        
        this.clipSize = this.imageClip.imageList.nImages;
        this.frame = this.imageClip.frameIndex;
    }
    
    
    this.update = function()
    {	
        var direction = TurnFrames.incOrDec(this.angle, this.targetAngle, 360);  // +1 or -1
        this.angle = TurnFrames.cleanAngle(this.angle + this.angularVelocity*this.timePassed*direction);
        
        // check if overshot target angle IS THERE EASIER WAY?
        if (TurnFrames.incOrDec(this.angle, this.targetAngle, 360) === 0 - direction) {
            this.angle = this.targetAngle;
        }
        
        // set the frame for the ImageClip
        this.frame = TurnFrames.angleToFrame(this.angle, this.clipSize);
        this.imageClip.frame = Math.round(this.frame);     // WHAT IF Math.floor() TO BE CONSISTENT?
        
        // print("this.angle:" + this.angle + " this.imageClip.frame:" + this.imageClip.frame);
        if (this.angle === this.targetAngle) {
            return true;
        } else {
            return false;
        }
    }
    
    // convert an angle to a "clean" angle between 0 and 360
    TurnFrames.cleanAngle = function(angle)
    {
        angle %= 360;
        if (angle < 0) { 
            return 360 + angle; 
        }
        return angle;
    }
    
    //
    // convert angle (degrees) to an ImageClip frame number where 
    //  the first frame is 0 degrees and the last 360 degrees
    TurnFrames.angleToFrame = function(angle, totalFrames)
    {	
        // find angle size of each segment
        var segment = 360.0/totalFrames;	
        
        // augment the angle by half a segment      // NEEDED? WHAT IF Math.floor() USED ABOVE?
        angle += segment/2;
        
        // loop at 360 back to 0 degrees    USE MODULO ?
        if (angle >= 360) { angle -= 360; }
        
        // return the frame
        return Math.floor(angle/segment);
    }
    
    //
    // given a looping sequence in both directions with a range of max,
    // if at n which direction (+ or -) is quickest to get to indDest
    TurnFrames.incOrDec = function(n, dest, max) 
    {
        // ensure integers
        
        var inc = 0;
        var dec = 0;
        
        if (n === dest) {
            return 0;
        } else if (n < dest) {
            inc = dest - n;            
            dec = n + (max - dest);
        } else if (n > dest) {
            inc = dest + (max - n);
            dec = n - dest;
        }
        
        if (inc > dec) {
            return -1;
        } else {
            return +1;
        }
    }
}

TurnFrames.prototype = new BaseFx("TurnFrames", BaseFx.END);


/*
		public static function turnInDuration(duration:uint,
											  startAngle:Number,
											  targetAngle:Number):AngleFramesFX 
		{	
			var angle:Number = cleanAngle(targetAngle - startAngle);
			if (angle > 180) { 
				angle = 360 - angle;
			}
			var angularVelocity:Number = angle/duration;
			return new AngleFramesFX(angularVelocity, startAngle, targetAngle);
		}
 */

